import { PlusOutlined } from '@ant-design/icons';
import { Image, Upload, message } from 'antd';
import React, { useEffect, useState } from 'react';

import type { GetProp, UploadFile, UploadProps } from 'antd';

type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];

const getBase64 = (file: FileType): Promise<string> =>
  new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result as string);
    reader.onerror = (error) => reject(error);
  });
// 允许上传的文件类型
const ALLOWED_FILE_TYPES = ['image/jpeg', 'image/png'];
// 最大文件大小 3MB
const MAX_FILE_SIZE = 3 * 1024 * 1024;

export default function UploadPicture({
  portraitList = [],
  maxCount = 1,
  onUploadSuccess,
  onFileRemove,
  disabled = false,
  title = '上传图片',
}: {
  portraitList?: string[];
  maxCount?: number;
  onUploadSuccess?: (fileIdList: string[]) => void;
  onFileRemove?: (file) => void;
  disabled?: boolean;
  title?: string;
}) {
  const [previewOpen, setPreviewOpen] = useState(false);
  const [previewImage, setPreviewImage] = useState('');
  const [fileList, setFileList] = useState<UploadFile[]>([]);
  const [fileSrcs, setFileSrcs] = useState<string[]>([]);
  const [previewIndex, setPreviewIndex] = useState(0);

  // 上传前校验文件类型和大小
  const beforeUpload: UploadProps['beforeUpload'] = (file) => {
    // 校验文件类型
    const isAllowedType = ALLOWED_FILE_TYPES.includes(file.type);
    if (!isAllowedType) {
      message.error('只能上传 JPG/PNG 格式的图片!');
      return Upload.LIST_IGNORE;
    }

    // 校验文件大小
    const isLtSize = file.size <= MAX_FILE_SIZE;
    if (!isLtSize) {
      message.error('图片大小不能超过 3MB!');
      return Upload.LIST_IGNORE;
    }

    return true;
  };

  const handlePreview = async (file: UploadFile) => {
    if (!file.url && !file.preview) {
      file.preview = await getBase64(file.originFileObj as FileType);
    }
    const currentIndex = fileList.findIndex((item) => item.uid === file.uid);
    setPreviewIndex(currentIndex);
    setPreviewImage(file.url || (file.preview as string));
    setPreviewOpen(true);
  };

  useEffect(() => {
    portraitList = portraitList.filter((item) => item != undefined && item != '');
    if (portraitList.length > 0) {
      setFileSrcs(portraitList);
      setFileList(
        portraitList.map((item) => ({
          uid: item,
          name: 'image.png',
          status: 'done',
          url: item,
          response: { success: item },
        })),
      );
    }
  }, [portraitList]);

  const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
    setFileList(newFileList);
    if (newFileList.length > 0 && newFileList[newFileList.length - 1]?.response) {
      setFileSrcs(fileSrcs.concat(newFileList[newFileList.length - 1]?.response?.success));
    }
    setFileSrcs(newFileList.map((item) => item.response?.success));
    if (newFileList[newFileList.length - 1]?.status === 'done') {
      onUploadSuccess?.(
        newFileList.map((item) => {
          if (item.response) {
            return item.response.success;
          }
          return 0;
        }),
      );
    }
  };

  const uploadButton = (
    <button style={{ border: 0, background: 'none' }} type="button">
      <PlusOutlined />
      <div style={{ marginTop: 8 }}>{title}</div>
    </button>
  );

  return (
    <>
      <Upload
        disabled={disabled}
        action="/api/file/oss/upload"
        listType="picture-card"
        fileList={fileList}
        onPreview={handlePreview}
        onChange={handleChange}
        onRemove={onFileRemove}
        beforeUpload={beforeUpload}
        maxCount={maxCount}
        data={{ group: 'njg' }}
      >
        {fileList.length >= maxCount ? null : uploadButton}
      </Upload>
      {previewImage && (
        <Image.PreviewGroup
          preview={{
            visible: previewOpen,
            current: previewIndex,
            onChange: (current) => {
              setPreviewIndex(current);
            },
            onVisibleChange: (visible) => {
              setPreviewOpen(visible);
            },
            afterOpenChange: (visible) => !visible && setPreviewImage(''),
          }}
          items={fileSrcs}
        />
      )}
    </>
  );
}
